//
//      Copyright Timothy Evans 2014 2015    timothy.evans@gsecraif.org
//
//      This file is part of gsecraif.
//
//      gsecraif is free software; you can redistribute it and/or modify
//      it under the terms of the GNU General Public License as published by
//      the Free Software Foundation; either version 3 of the License, or
//      (at your option) any later version.
//
//      See gsecraif.cpp
//
// =====================================================================
//
//! Parse the command line arguments.
//
// =====================================================================
// 
// Compile with g++
#include "parse_args.h"

using namespace std;

extern unsigned short int debuglevel;
extern bool showhashes;

void parse_args(int argc, char *argv[], char &action, int &numoffiles,
                unsigned short int &leftrotate, bool &transpose,
                vector<string> &compfilenames)
{
const short int maxnumoffiles = 255;    // maximum number of files programme
                                        // can split in to
short int argcn = 1;                    // used to parse args
short int suppliedfilename = 1;         // used to access each supplied
                                        // file name
string postfix = "000";                 // 3 character postfix
const string defprefix = "split";       // default prefix string
string prefixstring;                    // string to hold supplied prefix
// note that if the prefixstring is assigned the defprefix, then the length
// of prefixstring is limited to the length of defprefix, when argv is assigned

unsigned short int prefixarg=0;         // which argument is the prefix.
string tempstring;                      // temporary string to hold constructed
                                        // file name

unsigned short int filenamesstart = 1 ;
        // names of component files can be given on the command line
        // - this is where they start

char whatcompfilenames = 'd';          // what is the format of the
                                       // component filenames,
                                       // one of:
                                       // d default prefix
                                       // p prefix supplied
                                       // s component file names
                                       // supplied on command line

vector<string>::iterator compfileid;

bool args2parse = true;                // flag to signal end of args
                                       // in getops_long

// Parse arguments using getopt_long using example at:
// http://www.gnu.org/software/libc/manual/html_node/Getopt-Long-Option-Example.html

int optchr;    // integer returned from getopt_long

    while (args2parse)
        {
        static struct option long_options[] =
            {
                {"hash",       no_argument,       0, '#'},
                {"version",    no_argument,       0, 'V'},
                {"help",       no_argument,       0, 'h'},
                {"combine",    no_argument,       0, 'c'},
                {"transpose",  no_argument,       0, 't'},
                {"debug",      required_argument, 0, 'd'},
                {"nfiles",     required_argument, 0, 'n'},
                {"prefix",     required_argument, 0, 'p'},
                {"rotate",     required_argument, 0, 'r'},
                {0, 0, 0, 0}
            };
        /* getopt_long stores the option index here. */
        int option_index = 0;

        optchr = getopt_long (argc, argv, "Vh#ctn:d:r:p:",
                       long_options, &option_index);

        /* Detect the end of the options. */
        if (optchr == -1) {
            args2parse = false;
            }

        switch (optchr)
            {

            case 'V':
                action = 'v';
                break;
            case 'h':
                action = 'h';
                break;
            case '#':
                showhashes = true;
                break;
            case 'c':
                action = 'c';
                break;
            case 't':
                transpose = true;
                break;
            case 'n':
                numoffiles = atoi(optarg);
                if ((numoffiles > maxnumoffiles) || (numoffiles < 3)) {
                    action = 'u';
                    }
                break;
            case 'd':
                debuglevel = atoi(optarg);
                if ((debuglevel > 2) || (debuglevel < 0)) {
                    action = 'u';
                    }
                break;
            case 'p':
                whatcompfilenames = 'p';
                prefixstring = optarg;
                break;
            case 'r':
                leftrotate = atoi(optarg);
                if ((leftrotate > 7) || (leftrotate < 0)) {
                    action = 'u';
                    }
                break;

            default:
                args2parse = false;
                break;
            } //switch
        } // while


if (optind < argc) {
    // file names were supplied, check there are at least three file names
    if ((argc - optind) < 3) action='u';
    else { numoffiles = argc - optind; }

    // check that a prefix was not supplied with some files names
    if (whatcompfilenames == 'p') action = 'u';
    else { whatcompfilenames = 's'; }
    }

// build the list of component file names:
suppliedfilename = optind;
for (unsigned int compfileid=0; compfileid <= (numoffiles - 1); ++compfileid) {
    if (whatcompfilenames != 's') { 
        int2asciistr(postfix, compfileid);
        if (whatcompfilenames == 'p') {
            tempstring = prefixstring + postfix;
            }
        else {
            prefixstring = defprefix;               // assign default
            tempstring = prefixstring + postfix;
            } 
        compfilenames.push_back(tempstring);
        } // if (whatcompfilenames... 
    else if (whatcompfilenames != 'u') {
        // component filenames have been supplied on the command line
        tempstring = argv[suppliedfilename];
        compfilenames.push_back(tempstring);
        ++suppliedfilename;
        }
        
} // for (compfileid=0..


// Print some basic information if debug level > 0
if (debuglevel) {
    if (action == 'c') {
        cerr << "Combining files and output to standard out. \n";
        }
    else if (action == 's') {
        cerr << "Splitting from standard in. \n";
        }
    cerr << "Number of files: " << numoffiles << "\n";
    if (transpose) { cerr << "transpose \n"; }
    else {
        cerr << "Rotation: " << leftrotate << "\n";
        }
    cerr << "File names start at: " << optind << "\n";
    while (argcn < argc) {
        cerr << argv[argcn] << ", ";    
        ++argcn;
        }
        
    cerr << "\n";
    cerr << "Debug level: " << debuglevel << "\n----------\n";
    } // if (debug...



} // end of function

